package com.smartcommunity.service.building.impl;

import com.google.common.collect.Lists;
import com.smartcommunity.bean.enumeration.HouseTypeEnum;
import com.smartcommunity.bean.enumeration.ResultCode;
import com.smartcommunity.bean.model.Result;
import com.smartcommunity.dao.building.BuildingMapper;
import com.smartcommunity.dao.building.UnitMapper;
import com.smartcommunity.dao.village.HouseDao;
import com.smartcommunity.elasticsearch.house.HouseEsApi;
import com.smartcommunity.entity.building.*;
import com.smartcommunity.entity.village.Building;
import com.smartcommunity.entity.village.House;
import com.smartcommunity.es.common.EsBasedataEnum;
import com.smartcommunity.service.building.BuildingService;
import com.smartcommunity.service.people.PeopleService;
import com.smartcommunity.utils.StringUtils;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.collections.map.HashedMap;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author nieming
 * @descrition
 * @date 2020/5/12
 */
@Slf4j
@Service
public class BuildingServiceImpl implements BuildingService {
    @Autowired
    private BuildingMapper buildingMapper;
    @Autowired
    private UnitMapper unitMapper;
    @Autowired
    private HouseDao houseDao;
    @Autowired
    private HouseEsApi houseEsApi;
    @Autowired
    private PeopleService peopleService;

    @Override
    public BuildingEntity getBuilding(Long buildingId) {
        return buildingMapper.getBuilding(buildingId);
    }

    @Override
    public Result add(BuildingAddReq buildingAddReq) {
    	BuildingExitsReq buildingExitsReq = new BuildingExitsReq();
    	buildingExitsReq.setVillageCode(buildingAddReq.getVillageCode());
    	buildingExitsReq.setBuildingNo(buildingAddReq.getBuildingNo());
    	if(this.exits(buildingExitsReq)) {
    		return Result.error(ResultCode.VILLAGE_BUILD_EXSIT);
    	}
        BuildingEntity buildingEntity = new BuildingEntity();
        BeanUtils.copyProperties(buildingAddReq, buildingEntity);
        buildingEntity.setMrowTime(new Date());
        buildingEntity.setRowTime(new Date());

        //根据单元信息组装房屋信息
        List<UnitAddReq> units = buildingAddReq.getUnits();
        List<House> houses = Lists.newArrayList();
        List<UnitEntity> unitEntities = Lists.newArrayList();
        Integer maxFloorCounts = 0;
        //去重判断
        Map<String,UnitEntity> unitEntityMap = new HashedMap();
        for (UnitAddReq unitAddReq : units) {
            String mapKey =buildingAddReq.getVillageCode()+"_"+buildingAddReq.getBuildingNo()+"_"+ unitAddReq.getUnitNo();
            if(unitEntityMap.containsKey(mapKey)) {  //去重判断
                continue;
            }
            UnitEntity unitEntity = new UnitEntity();
            BeanUtils.copyProperties(unitAddReq, unitEntity);
            unitEntity.setVillageCode(buildingAddReq.getVillageCode());
            unitEntity.setBuildingNo(buildingAddReq.getBuildingNo());
            unitEntity.setUnitOrder(unitAddReq.getUnitOrder());
            unitEntity.setMrowTime(new Date());
            unitEntity.setRowTime(new Date());
            unitEntities.add(unitEntity);

            if (unitAddReq.getFloorEnd() > maxFloorCounts) {
                maxFloorCounts = unitAddReq.getFloorEnd();
            }
            houses.addAll(generateHouses(buildingAddReq.getVillageCode(), buildingAddReq.getBuildingNo(), unitAddReq.getUnitNo(), unitAddReq.getFloorStart(),unitAddReq.getFloorEnd(),unitAddReq.getHouseNoStart(), unitAddReq.getHouseCounts()));
            unitEntityMap.put(mapKey,unitEntity);
        }
//        if(units.size()>8) {
//            return Result.error(ResultCode.VILLAGE_BUILD_UNIT);
//        }
        buildingEntity.setUnitTotal(units.size());
        buildingEntity.setFloorTotal(maxFloorCounts);
        buildingEntity.setHouseTotal(houses.size());
        unitMapper.addBatch(unitEntities);
        buildingMapper.add(buildingEntity);
        houseDao.insertHouse(houses);
        //入库ES-basedata
        houseEsApi.batchSaveOrUpdateHouse(houses);
        return Result.ok();
    }

    @Override
    public List<Building> list(BuildingListReq buildingListReq) {
        return buildingMapper.list(buildingListReq);
    }

    @Override
    public boolean exits(BuildingExitsReq buildingExitsReq) {
        BuildingEntity buildingEntity = buildingMapper.exits(buildingExitsReq);
        if (null != buildingEntity) {
            if (null == buildingExitsReq.getId() || (null != buildingExitsReq.getId() && buildingExitsReq.getId().intValue() != buildingEntity.getId().intValue())) {
                return true;
            }
        }
        return false;
    }

    @Override
	public BuildingEntity getExistBildings(BuildingExitsReq buildingExitsReq) {
		return buildingMapper.exits(buildingExitsReq);
	}

    @Override
    public Result edit(BuildingEditReq buildingEditReq) {
        //查询楼栋编号是否存在
    	BuildingExitsReq buildingExitsReq = new BuildingExitsReq();
    	buildingExitsReq.setId(buildingEditReq.getId());
    	buildingExitsReq.setVillageCode(buildingEditReq.getVillageCode());
    	buildingExitsReq.setBuildingNo(buildingEditReq.getBuildingNo());
    	if(this.exits(buildingExitsReq)) {
    		return Result.error(ResultCode.VILLAGE_BUILD_EXSIT);
    	}

        BuildingEntity buildingEntityOld = getBuilding((long)buildingEditReq.getId());
        //删除楼栋房屋信息
        houseDao.deleteHouseByBuilding(buildingEntityOld.getVillageCode(), buildingEntityOld.getBuildingNo());
        //删除楼栋单元信息
        unitMapper.deleteUnitByBuilding(buildingEntityOld.getVillageCode(), buildingEntityOld.getBuildingNo());

        BuildingEntity buildingEntityNew = new BuildingEntity();
        BeanUtils.copyProperties(buildingEditReq, buildingEntityNew);
        buildingEntityNew.setMrowTime(new Date());



        //根据单元信息生产房屋信息
        List<UnitAddReq> units = buildingEditReq.getUnits();
        List<UnitEntity> unitEntities = Lists.newArrayList();
        List<House> houses = Lists.newArrayList();
        Integer maxFloorCounts = 0;
        for (UnitAddReq unitAddReq : units) {
            UnitEntity unitEntity = new UnitEntity();
            BeanUtils.copyProperties(unitAddReq, unitEntity);
            unitEntity.setVillageCode(buildingEditReq.getVillageCode());
            unitEntity.setBuildingNo(buildingEditReq.getBuildingNo());
            unitEntity.setMrowTime(new Date());
            unitEntity.setRowTime(new Date());
            unitEntity.setUnitOrder(unitAddReq.getUnitOrder());
            unitEntities.add(unitEntity);

            if (unitAddReq.getFloorEnd() > maxFloorCounts) {
                maxFloorCounts = unitAddReq.getFloorEnd();
            }
            houses.addAll(generateHouses(buildingEditReq.getVillageCode(), buildingEditReq.getBuildingNo(), unitAddReq.getUnitNo(), unitAddReq.getFloorStart(),unitAddReq.getFloorEnd(),unitAddReq.getHouseNoStart(), unitAddReq.getHouseCounts()));
        }
//        if(units.size()>8) {
//            return Result.error(ResultCode.VILLAGE_BUILD_UNIT);
//        }
        buildingEntityNew.setUnitTotal(units.size());
        buildingEntityNew.setFloorTotal(maxFloorCounts);
        buildingEntityNew.setHouseTotal(houses.size());

        unitMapper.addBatch(unitEntities);
        buildingMapper.edit(buildingEntityNew);
        houseDao.insertHouse(houses);
        //入库ES-basedata
        BoolQueryBuilder boolQueryBuilder = buildDeleteQueryBuilder(buildingEntityOld.getVillageCode(), buildingEntityOld.getBuildingNo());
        houseEsApi.deleteQuery(boolQueryBuilder);
        houseEsApi.batchSaveOrUpdateHouse(houses);
        //如果修改了楼栋号则需要修改人房关系
        if(buildingEntityOld.getBuildingNo()!=null && buildingEditReq.getBuildingNo()!=null
        		&& !StringUtils.equals(buildingEntityOld.getBuildingNo(), buildingEditReq.getBuildingNo())) {
        	updatePeopleBuildingNo(buildingEntityOld.getVillageCode(), buildingEntityOld.getBuildingNo(), buildingEditReq.getBuildingNo());
        }
        return Result.ok();
    }

    private void updatePeopleBuildingNo(String villageCode, String oldBuildingNo, String newBuildingNo) {
    	Map<String, Object> param = new HashMap<>(3);
    	param.put("villageCode",villageCode);
    	param.put("oldBuildingNo",oldBuildingNo);
    	param.put("newBuildingNo",newBuildingNo);
    	houseDao.updatePeopleBuildingNo(param);
    	try {
    		peopleService.syncDataToEs(villageCode, newBuildingNo);
    	}catch (Exception e) {
			log.error("修改basedata索引的楼栋号失败", e);
		}
	}

	@Override
    public void delete(Long buildingId) {
        BuildingEntity buildingEntity = getBuilding(buildingId);
        unitMapper.deleteUnitByBuilding(buildingEntity.getVillageCode(), buildingEntity.getBuildingNo());
        buildingMapper.delete(buildingId);
        houseDao.deleteHouseByBuilding(buildingEntity.getVillageCode(), buildingEntity.getBuildingNo());
        //删除ES-basedata
        BoolQueryBuilder boolQueryBuilder = buildDeleteQueryBuilder(buildingEntity.getVillageCode(), buildingEntity.getBuildingNo());
        houseEsApi.deleteQuery(boolQueryBuilder);
    }
    
    private BoolQueryBuilder buildDeleteQueryBuilder(String villageCode, String buildingNo) {
    	BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("dataType", EsBasedataEnum.HOUSE.getIntValue()));
        boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("detailAddress.villageCode", villageCode));
        boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("detailAddress.buildingNo", buildingNo));
        return boolQueryBuilder;
    }

    @Override
    public BuildingDetailResp detail(Long buildingId) {
        BuildingDetailResp buildingDetailResp = new BuildingDetailResp();
        BuildingEntity building = buildingMapper.getBuilding(buildingId);
        if (null != building) {
            BeanUtils.copyProperties(building, buildingDetailResp);
            List<UnitEntity> unitEntities = unitMapper.queryBuildingUnits(building);
            buildingDetailResp.setUnits(unitEntities);
        }
        return buildingDetailResp;
    }

    /**
     * 根据楼层户数生成房屋信息
     * @param villageCode 小区编码
     * @param buildingNo 楼栋号
     * @param unitNo 单元号
     * @param floorStart 楼层起始值
     * @param floorEnd 楼层结束值
     * @param houseNoStart 房号起始值
     * @param houseCounts 房屋数量
     * @return
     */
    public List<House> generateHouses(String villageCode, String buildingNo, String unitNo, Integer floorStart,Integer floorEnd, Integer houseNoStart,Integer houseCounts) {
        List<House> houseList = Lists.newArrayList();
        for (int floorNo = floorStart; floorNo <= floorEnd; floorNo++) {
            for (int houseCount = 0; houseCount < houseCounts; houseCount++) {
                Integer houseNo = houseCount+houseNoStart;
                House house = new House();
                house.setVillageCode(villageCode);
                house.setBuildingNo(buildingNo);
                house.setUnitNo(unitNo);
                house.setFloor(String.valueOf(floorNo));
                if (houseNo < 10) {
                    house.setHouseNo(floorNo + "0" + houseNo);
                    house.setHouseName(floorNo + "0" + houseNo);
                } else {
                    house.setHouseNo(floorNo + "" + houseNo);
                    house.setHouseName(floorNo + "" + houseNo);
                }
                house.setType(HouseTypeEnum.self.getValue());
                house.setRowTime(new Date());
                house.setMrowTime(new Date());
                houseList.add(house);
            }
        }
        return houseList;
    }

}
